home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Environments / PowerMacOberon feb96 / Source / Backup.Mod (.txt) < prev    next >
Oberon Text  |  1995-09-18  |  13KB  |  344 lines

  1. Syntax10.Scn.Fnt
  2. FoldElems
  3. Syntax10.Scn.Fnt
  4. (* ----------------------------------------------------------
  5. Backup does an incremental backup between two directories, i.e. only the files that
  6. have changed since the last backup are copied.
  7.     Backup.WriteFiles ( {src  dst} ~ | "^")
  8. src and dst are given as Macintosh path names starting with the volume name
  9. and ending with ":". If a path name contains blanks it must be written under quotes.
  10. All entries in dst which are not also in src are deleted so that after the backup
  11. the contents of dst will be equal to the contents of src.
  12. Example:
  13.     Backup.WriteFiles    Othello:Text:Lectures:EiP:    hm:Backup:EiP: ~
  14. ----------------------------------------------------------*)
  15. Syntax10i.Scn.Fnt
  16. StampElems
  17. Alloc
  18. 18 Sep 95
  19. Syntax10.Scn.Fnt
  20.     VAR i: INTEGER;
  21. BEGIN
  22.     i := 0; WHILE in[i] # 0X DO out[i+1] := in[i]; INC(i) END;
  23.     out[0] := CHR(i)
  24. END MakeStr255;
  25. Syntax10.Scn.Fnt
  26.     VAR res: INTEGER;
  27. BEGIN
  28.     NEW(par);
  29.     par.ioCompletion := 0; par.ioNamePtr := SYSTEM.ADR(spec.name);
  30.     par.ioVRefNum := spec.vRefNum; par.ioDirID := spec.parID; par.ioFDirIndex := 0;
  31.     res := Sys.PBGetCatInfo(par); ASSERT(res = 0)
  32. END GetFileInfo;
  33. Syntax10.Scn.Fnt
  34.     VAR res: INTEGER;
  35. BEGIN
  36.     NEW(par);
  37.     par.ioCompletion := 0; par.ioNamePtr := SYSTEM.ADR(spec.name);
  38.     par.ioVRefNum := spec.vRefNum; par.ioDrDirID := spec.parID; par.ioFDirIndex := 0;
  39.     res := Sys.PBGetCatInfo(par); ASSERT(res = 0)
  40. END GetDirInfo;
  41. Syntax10.Scn.Fnt
  42.     VAR ch, start: CHAR; i: INTEGER;
  43. BEGIN
  44.     REPEAT In.Char(ch) UNTIL (ch > " ") OR ~In.Done;
  45.     i := 1;
  46.     IF (ch = '"') OR (ch = "'") THEN
  47.         start := ch; In.Char(ch);
  48.         WHILE In.Done & (ch # start) DO s[i] := ch; INC(i); In.Char(ch) END;
  49.         In.Char(ch);
  50.     ELSE
  51.         WHILE In.Done & (ch > " ") DO s[i] := ch; INC(i); In.Char(ch) END
  52.     END;
  53.     s[i] := 0X; s[0] := CHR(i-1);
  54.     FOR i := 1 TO ORD(s[0]) DO
  55.         IF (s[i] >= CHR(129)) & (s[i] <= CHR(133)) THEN s[i] := umlaut[ORD(s[i])-129] END
  56. END ReadString;
  57. Syntax10.Scn.Fnt
  58.     VAR i, j: INTEGER;
  59. BEGIN
  60.     FOR i := 1 TO ORD(s[0]) DO
  61.         FOR j := 0 TO LEN(umlaut)-1 DO
  62.             IF s[i] = umlaut[j] THEN s[i] := CHR(129 + j) END
  63.         END
  64.     END;
  65.     s[0] := " "; s[i] := 0X; Out.String(s)
  66. END PrintString;
  67. Syntax10.Scn.Fnt
  68.     VAR i: INTEGER;
  69. BEGIN
  70.     IF a[0] # b[0] THEN RETURN FALSE END;
  71.     i := ORD(a[0]); WHILE (i > 0) & (a[i] = b[i]) DO DEC(i) END;
  72.     RETURN i = 0
  73. END EqualString;
  74. Syntax10.Scn.Fnt
  75. BEGIN
  76.     Out.String(" --- ");
  77.     CASE n OF
  78.        -33: Out.String("directory full")
  79.     | -34: Out.String("disk full")
  80.     | -35: Out.String("volume not found")
  81.     | -37: Out.String("bad file or volume name")
  82.     | -43: Out.String("file not found")
  83.     | -44, -46: Out.String("volume locked")
  84.     | -45: Out.String("file locked")
  85.     | -47: Out.String("file busy or directory not empty")
  86.     | -49: Out.String("file already open for writing")
  87.     ELSE Out.F("error #", n)
  88.     END;
  89.     Out.Ln
  90. END Err;
  91. Syntax10.Scn.Fnt
  92.     VAR f: File;
  93. BEGIN
  94.     NEW(f); f.next := NIL; f.spec := spec; f.touched := FALSE;
  95.     f.date := info.ioFlMdDat; f.len := info.ioFlLgLen; f.rlen := info.ioFlRLgLen;
  96.     f.creator := info.ioFlFndrInfo.fdCreator; f.type := info.ioFlFndrInfo.fdType;
  97.     IF f.len > maxLen THEN maxLen := f.len END;
  98.     IF f.rlen > maxLen THEN maxLen := f.rlen END;
  99.     RETURN f
  100. END NewFile;
  101. Syntax10.Scn.Fnt
  102.     VAR g: File;
  103. BEGIN
  104.     g := d.files;
  105.     WHILE (g # NIL) & ~EqualString(f.spec.name, g.spec.name) DO g := g.next END;
  106.     RETURN g
  107. END ThisFile;
  108. Syntax10.Scn.Fnt
  109. FoldElems
  110. Syntax10.Scn.Fnt
  111. PrintString(f.spec.name);
  112.     IF g # NIL THEN
  113.         res := Sys.FSpDelete(g.spec); ASSERT(res = 0, 99)
  114.     ELSE
  115.         NEW(g);
  116.         FOR i := 0 TO ORD(f.spec.name[0]) DO s[i] := f.spec.name[i] END;
  117.         res := Sys.FSMakeFSSpec(dt.spec.vRefNum, dt.dirID, s, g.spec); ASSERT(res = fnfErr, 98)
  118.     END;
  119.     res := Sys.FSpCreate(g.spec, f.creator, f.type, Sys.smSystemScript); IF res # 0 THEN Err(res); RETURN END;
  120. Syntax10i.Scn.Fnt
  121. Syntax10.Scn.Fnt
  122. res := Sys.FSpOpenDF(f.spec, 0, fRef); IF res # 0 THEN Err(res); RETURN END;
  123.     res := Sys.FSpOpenDF(g.spec, 0, gRef); IF res # 0 THEN Err(res); RETURN END;
  124.     res := Sys.FSRead(fRef, f.len, SYSTEM.ADR(buf^)); ASSERT(res = 0, 94);
  125.     res := Sys.FSWrite(gRef, f.len, SYSTEM.ADR(buf^)); IF res # 0 THEN Err(res) END;
  126.     res := Sys.FSClose(fRef); ASSERT(res = 0, 92);
  127.     res := Sys.FSClose(gRef); ASSERT(res = 0, 91);
  128. Syntax10.Scn.Fnt
  129. IF f.rlen > 0 THEN
  130.         res := Sys.FSpOpenRF(f.spec, 0, fRef); IF res # 0 THEN Err(res); RETURN END;
  131.         res := Sys.FSpOpenRF(g.spec, 0, gRef); IF res # 0 THEN Err(res); RETURN END;
  132.         res := Sys.FSRead(fRef, f.rlen, SYSTEM.ADR(buf^)); ASSERT(res = 0, 88);
  133.         res := Sys.FSWrite(gRef, f.rlen, SYSTEM.ADR(buf^)); IF res # 0 THEN Err(res) END;
  134.         res := Sys.FSClose(fRef); ASSERT(res = 0, 86);
  135.         res := Sys.FSClose(gRef); ASSERT(res = 0, 85);
  136.         Out.String(" + resources")
  137.     END;
  138.     VAR res, i: INTEGER; s: Sys.Str255; fRef, gRef: INTEGER; info: FileInfo;
  139. BEGIN
  140. create empty g on dt
  141. copy data fork
  142. copy resource fork
  143.     Out.String(" saved$"); INC(savedFiles)
  144. END SaveFile;
  145. Syntax10.Scn.Fnt
  146.     VAR d: Directory; info: DirInfo; res: INTEGER;
  147. BEGIN
  148.     NEW(d); d.next := NIL; d.files := NIL; d.dirs := NIL;
  149.     d.spec := spec;
  150.     GetDirInfo(spec, info); d.dirID := info.ioDrDirID; d.date := info.ioDrMdDat;
  151.     RETURN d
  152. END NewDir;
  153. Syntax10.Scn.Fnt
  154.     VAR spec: Sys.FSSpec; s: Sys.Str255; res, i: INTEGER; dummy: LONGINT;
  155. BEGIN
  156.     FOR i := 0 TO ORD(df.spec.name[0]) DO s[i] := df.spec.name[i] END;
  157.     res := Sys.FSMakeFSSpec(parent.spec.vRefNum, parent.dirID, s, spec); ASSERT(res = fnfErr, 29);
  158.     res := Sys.FSpDirCreate(spec, Sys.smSystemScript, dummy); ASSERT(res = 0, 30);
  159.     dt := NewDir(spec)
  160. END CreateDir;
  161. Syntax10.Scn.Fnt
  162.     VAR g: File;
  163. BEGIN
  164.     g := d.dirs;
  165.     WHILE (g # NIL) & ~EqualString(f.spec.name, g.spec.name) DO g := g.next END;
  166.     RETURN g
  167. END ThisDir;
  168. Syntax10.Scn.Fnt
  169.     VAR f: File; i: INTEGER;
  170. BEGIN
  171.     FOR i := 1 TO indent DO Out.String("  ") END;
  172.     Out.String("--- "); PrintString(d.spec.name); Out.Ln;
  173.     f := d.files;
  174.     WHILE f # NIL DO
  175.         FOR i := 1 TO indent DO Out.String("  ") END;
  176.         Out.String("   "); PrintString(f.spec.name); Out.Ln;
  177.         f := f.next
  178.     END;
  179.     f := d.dirs;
  180.     WHILE f # NIL DO PrintDir(f(Directory), indent + 1); f := f.next END
  181. END PrintDir;
  182. Syntax10.Scn.Fnt
  183. Syntax10i.Scn.Fnt
  184.     VAR f: File; d1: Directory; par: FileInfo; res, n, i: INTEGER; spec: Sys.FSSpec; s: Sys.Str255;
  185. BEGIN
  186.     n := 1; Out.Char(prompt);
  187.     NEW(par); par.ioCompletion := 0; par.ioVRefNum := d.spec.vRefNum;
  188.     LOOP
  189.         s[0] := 0X; par.ioNamePtr := SYSTEM.ADR(s);
  190.         par.ioDirID := d.dirID;
  191.         par.ioFDirIndex := n; INC(n);
  192.         res := Sys.PBGetCatInfo(par);
  193.         IF res = 0 THEN
  194.             IF par.ioFlFndrInfo.fdFlags >= 0 THEN (*no alias: alias files have bit 15 set*)
  195.                 res := Sys.FSMakeFSSpec(d.spec.vRefNum, d.dirID, s, spec); ASSERT(res = 0);
  196.                 IF ODD(par.ioFlAttrib DIV 16) THEN (*directory*)
  197.                     d1 := NewDir(spec); d1.next := d.dirs; d.dirs := d1
  198.                 ELSE (*file*)
  199.                     f := NewFile(spec, par); f.next := d.files; d.files := f
  200.                 END
  201.             END
  202.         ELSIF res = fnfErr THEN EXIT
  203.         ELSE HALT(20)
  204.         END
  205.     END;
  206.     f := d.dirs;
  207.     WHILE f # NIL DO FillDir(f(Directory), prompt); f := f.next END
  208. END FillDir;
  209. Syntax10.Scn.Fnt
  210.     VAR f, g: File; first: BOOLEAN;
  211. BEGIN
  212.     f := df.files; first := TRUE;
  213.     WHILE f # NIL DO
  214.         g := ThisFile(dt, f);
  215.         IF (g = NIL) OR (f.date > g.date) THEN
  216.             IF first THEN Out.String("-- "); PrintString(df.spec.name); Out.Ln; first := FALSE END;
  217.             SaveFile(f, g, dt)
  218.         END;
  219.         g.touched := TRUE;
  220.         f := f.next
  221.     END;
  222.     f := df.dirs;
  223.     WHILE f # NIL DO
  224.         g := ThisDir(dt, f);
  225.         IF g = NIL THEN CreateDir(f(Directory), dt, g) END;
  226.         SaveDir(f(Directory), g(Directory));
  227.         g.touched := TRUE;
  228.         f := f.next
  229. END SaveDir;
  230. Syntax10.Scn.Fnt
  231. Syntax10i.Scn.Fnt
  232.     VAR f: File; first: BOOLEAN; res: INTEGER; inf: DirInfo;
  233. BEGIN (*delete redundant files in d*)
  234.     f := d.files; first := TRUE;
  235.     WHILE f # NIL DO
  236.         IF ~f.touched THEN
  237.             IF first THEN Out.String("-- "); PrintString(d.spec.name); Out.Ln; first := FALSE END;
  238.             res := Sys.FSpDelete(f.spec);
  239.             PrintString(f.spec.name); Out.String(" deleted$")
  240.         END;
  241.         f := f.next
  242.     END;
  243.     f := d.dirs;
  244.     WHILE f # NIL DO
  245.         CleanupDir(f(Directory));
  246.         res := Sys.FSpDelete(f.spec);
  247.         IF res = 0 THEN (*was empty*)
  248.             IF first THEN Out.String("-- "); PrintString(d.spec.name); Out.Ln; first := FALSE END;
  249.             PrintString(f.spec.name); Out.String(" deleted$")
  250.         END;
  251.         f := f.next
  252. END CleanupDir;
  253. Syntax10b.Scn.Fnt
  254. Syntax10.Scn.Fnt
  255.     VAR path: Sys.Str255; df, dt: Directory; res: INTEGER; spec: Sys.FSSpec;
  256. BEGIN
  257.     In.Open; Out.Open; savedFiles := 0;
  258.     LOOP
  259.         ReadString(path);
  260.         IF (path[0] = 0X) OR (path[1] = "~") THEN EXIT END;
  261.         res := Sys.FSMakeFSSpec(0, 0, path, spec);
  262.         IF res # 0 THEN Out.F("-- Invalid source directory. res = #$", res); EXIT END;
  263.         df := NewDir(spec);
  264.         ReadString(path);
  265.         res := Sys.FSMakeFSSpec(0, 0, path, spec);
  266.         IF res # 0 THEN Out.F("-- Invalid destination directory. res = #$", res); EXIT END;
  267.         dt := NewDir(spec);
  268.         maxLen := 0;
  269.         Out.String("Reading directories");
  270.         FillDir(df, "-"); FillDir(dt, "+");
  271.         Out.Ln;
  272.         NEW(buf, maxLen);
  273.         (*PrintDir(df, 0); PrintDir(dt, 0);*)
  274.         SaveDir(df, dt);
  275.         CleanupDir(dt)
  276.     END;
  277.     Out.F("$# files saved$", savedFiles);
  278.     Out.Close; buf := NIL
  279. END WriteFiles;
  280. Documentation
  281. MODULE Backup;    (* HM 
  282. IMPORT Sys, In, Out, SYSTEM;
  283. CONST
  284.     fnfErr = -43;
  285.     File = POINTER TO FileDesc;
  286.     FileDesc = RECORD
  287.         next: File;
  288.         spec: Sys.FSSpec;
  289.         date, len, rlen, creator, type: LONGINT;
  290.         touched: BOOLEAN
  291.     END;
  292.     Directory = POINTER TO DirectoryDesc;
  293.     DirectoryDesc = RECORD (FileDesc)
  294.         dirID: LONGINT;
  295.         files: File;    (*the files in this directory*)
  296.         dirs: File    (*the subdirectories in this directory*)
  297.     END;
  298.     DirInfo = POINTER TO DirInfoDesc;
  299.     DirInfoDesc = RECORD (Sys.CInfoPBRec)
  300.         ioDrUsrWds: Sys.DInfo;
  301.         ioDrDirID: LONGINT;
  302.         ioDrNmFls: INTEGER;
  303.         f3: ARRAY 9 OF INTEGER;
  304.         ioDrCrDat: LONGINT;
  305.         ioDrMdDat: LONGINT;
  306.         ioDrBkDat: LONGINT;
  307.         ioDrFndrInfo: Sys.DXInfo;
  308.         ioDrParID: LONGINT
  309.     END;
  310.     FileInfo = Sys.CInfoPBFilePtr;
  311.     maxLen: LONGINT;    (*max. file length (determines buffer sizes)*)
  312.     buf: POINTER TO ARRAY OF CHAR;    (*files are copied via this buffer*)
  313.     savedFiles: LONGINT;    (*number of saved files*)
  314.     umlaut: ARRAY 5 OF CHAR;    (*conversion of Oberon umlauts to Mac umlauts*)
  315. (*--- toolbox*)
  316. PROCEDURE MakeStr255 (VAR in: ARRAY OF CHAR; VAR out: Sys.Str255);    
  317. PROCEDURE GetFileInfo (spec: Sys.FSSpec; VAR par: FileInfo);    
  318. PROCEDURE GetDirInfo (spec: Sys.FSSpec; VAR par: DirInfo);    
  319. (*--- auxiliaries*)
  320. PROCEDURE ReadString (VAR s: ARRAY OF CHAR);    
  321. PROCEDURE PrintString (s: ARRAY OF CHAR);    
  322. PROCEDURE EqualString (a, b: ARRAY OF CHAR): BOOLEAN;    
  323. PROCEDURE Err (n: INTEGER);    
  324. (*--- files*)
  325. PROCEDURE NewFile (spec: Sys.FSSpec; info: FileInfo): File;    
  326. PROCEDURE ThisFile (d: Directory; f: File): File;    
  327. PROCEDURE SaveFile (f: File; VAR g: File; dt: Directory);    
  328. (*--- directories*)
  329. PROCEDURE NewDir (spec: Sys.FSSpec): Directory;    
  330. PROCEDURE CreateDir (df, parent: Directory; VAR dt: File);    
  331. PROCEDURE ThisDir (d: Directory; f: File): File;    
  332. (*PROCEDURE PrintDir (d: Directory; indent: INTEGER);    
  333. PROCEDURE FillDir (d: Directory; prompt: CHAR);    
  334. PROCEDURE SaveDir (df, dt: Directory);    
  335. PROCEDURE CleanupDir (d: Directory);    
  336. PROCEDURE WriteFiles*;    
  337. BEGIN
  338.     umlaut[0] := CHR(133);    (*Oe*)
  339.     umlaut[1] := CHR(134);    (*Ue*)
  340.     umlaut[2] := CHR(138);    (*ae*)
  341.     umlaut[3] := CHR(154);    (*oe*)
  342.     umlaut[4] := CHR(159);    (*ue*)
  343. END Backup.
  344.